package org.simple.rpc.redis.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

/**
 * redis的Java客户端Jedis工具类
 *
 * @author
 */
public class RedisUtils {
	/**
	 * 非切片客户端链接
	 */
	private static Jedis jedis;
	/**
	 * 非切片链接池
	 */
	private static JedisPool jedisPool;
	/**
	 * 切片客户端链接
	 */
	private static ShardedJedis shardedJedis;
	/**
	 * 切片链接池
	 */
	private static ShardedJedisPool shardedJedisPool;

	// 静态方法 初始化redis连接
	static {
		ResourceBundle bundle = ResourceBundle.getBundle("redis");
		if (bundle == null) {
			throw new IllegalArgumentException(
					"[redis.properties] is not found!");
		}
		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxIdle(Integer.valueOf(bundle
				.getString("redis.pool.maxIdle")));
		config.setTestOnBorrow(Boolean.valueOf(bundle
				.getString("redis.pool.testOnBorrow")));
		config.setTestOnReturn(Boolean.valueOf(bundle
				.getString("redis.pool.testOnReturn")));
		jedisPool = new JedisPool(config, bundle.getString("redis.ip"),
				Integer.valueOf(bundle.getString("redis.port")));
		// slave链接可以配置多个做集群
		List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
		shards.add(new JedisShardInfo(bundle.getString("redis.ip"), 6379,
				"master"));
		// 构造池
		shardedJedisPool = new ShardedJedisPool(config, shards);
		shardedJedis = shardedJedisPool.getResource();
		jedis = jedisPool.getResource();
	}

	/**
	 * 构造函数
	 */
	public RedisUtils() {
	}

	/**
	 * 存储字符串
	 * 
	 * @param key
	 * @param value
	 */
	public static void saveString(String key, String value) {
		try {
			shardedJedis.set(key, value);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
	}

	/**
	 * 存储字符串并设置有效时间
	 * 
	 * @param key
	 * @param value
	 * @param lifeSeconds
	 *            有效时间
	 */
	public static void saveString(String key, String value, Integer lifeSeconds) {
		try {
			shardedJedis.setex(key, lifeSeconds, value);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
	}

	/**
	 * 判断一个key是否存在
	 * 
	 * @param key
	 * @return
	 */
	public static Boolean existsKey(String key) {
		Boolean boolean1 = false;
		try {
			boolean1 = shardedJedis.exists(key);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
		return boolean1;
	}

	/**
	 * 判断一个key是否存在
	 * 
	 * @param key
	 * @return
	 */
	public static Boolean existsKey(byte[] key) {
		Boolean boolean1 = false;
		try {
			boolean1 = shardedJedis.exists(key);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
		return boolean1;
	}

	/**
	 * 根据key获得value
	 * 
	 * @param key
	 * @return
	 */
	public static String getValue(String key) {
		String value = null;

		try {
			shardedJedis.get(key);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
		return value;
	}

	/**
	 * 根据key获得value
	 * 
	 * @param key
	 * @return
	 */
	public static byte[] getValue(byte[] key) {
		byte[] value = null;

		try {
			shardedJedis.get(key);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
		return value;
	}

	/**
	 * 存储object对象
	 * 
	 * @param key
	 * @param object
	 */
	public static void setObjet(String key, Object object) {
		try {
			shardedJedis.set(key.getBytes(), SerializeUtil.serializes(object));
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
	}

	/**
	 * 存储object对象(有存活时间的)
	 * 
	 * @param key
	 * @param lifeSeconds
	 *            分钟
	 * @param object
	 */
	public static void setObjet(String key, Integer lifeSeconds, Object object) {
		try {
			shardedJedis.setex(key.getBytes(), lifeSeconds,
					SerializeUtil.serializes(object));
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
	}

	/**
	 * 取得object对象
	 * 
	 * @param key
	 * @return
	 */
	public static Object getObject(String key) {
		Object object = new Object();

		try {
			object = SerializeUtil
					.unserializes(shardedJedis.get(key.getBytes()));
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
		return object;
	}
	/**
	 * 存储list对象
	 * @param listName
	 * @param listValues
	 */
	public static void setList(String listName, List<String> listValues) {
		try {
			for (int i = 0; i < listValues.size(); i++) {
				shardedJedis.lpush(listName, listValues.get(i));
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
	}

	/**
	 * 获得list
	 * @param listName
	 * @return
	 */
	public static List<String> getList(String listName) {
		List<String> list = new ArrayList<String>();
		try {
			while (shardedJedis.llen(listName) > 0) {
				list.add(shardedJedis.lpop(listName));
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
		return list;
	}
	
	/**
	 * 存储Object list
	 * @param listName
	 * @param listObjects
	 */
	@SuppressWarnings("rawtypes")
	public static void setListObject(String listName, List listObjects) {
		try {
			for (int i = 0; i < listObjects.size(); i++) {
				shardedJedis.lpush(listName.getBytes(), SerializeUtil.serializes(listObjects.get(i)));
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
	}
	
	/**
	 * 获得list Object
	 * @param listName
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List getListObject(String listName) {
		List list = new ArrayList();
		try {
			while (shardedJedis.llen(listName) > 0) {
				list.add(SerializeUtil.unserializes(shardedJedis.lpop(listName.getBytes())));
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			shardedJedisPool.close();
		}
		return list;
	}
}
